package com.quwan.manager.service.impl;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.quwan.common.result.PageResult;
import com.quwan.entity.TFinanceData;
import com.quwan.entity.TMemberBalanceLog;
import com.quwan.entity.TPreserveData;
import com.quwan.entity.TSpreadData;

import com.quwan.manager.controller.dto.BalanceLogDTO;
import com.quwan.manager.controller.dto.DashboardVo;
import com.quwan.manager.service.DataDashboardService;
import com.quwan.mapper.*;
import com.quwan.utils.DateUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;


import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author quan
 * @date 2021-07-26 16:53
 */
@SuppressWarnings("Duplicates")
@Slf4j
@Service
@RequiredArgsConstructor
public class DataDashboardServiceImpl implements DataDashboardService {
    private final TSpreadDataMapper spreadDataMapper;
    private final TFinanceDataMapper financeDataMapper;
    private final TMemberBalanceLogMapper memberBalanceLogMapper;
    private final TPreserveDataMapper preserveDataMapper;


    @Override
    public PageResult<TSpreadData> getSpreadDataList(int page, int size, String beginTime, String endTime, String curWeek, String curMonth) {
        if (StringUtils.isNotBlank(curWeek) || StringUtils.isNotBlank(curMonth)) {
            beginTime = "";
            endTime = "";
            if (StringUtils.isNotBlank(curMonth)) {
                page = 1;
                size = 31;
            }
            if (StringUtils.isNotBlank(curWeek) && StringUtils.isNotBlank(curMonth)) {
                curWeek = "";
                curMonth = "";
            }
        }

        IPage<TSpreadData> res = spreadDataMapper.selectSearchSpreadDataList(new Page<>(page, size), beginTime, endTime, curWeek, curMonth);
        return new PageResult<TSpreadData>()
                .setCurrent(res.getCurrent())
                .setPages(res.getPages())
                .setSize(res.getSize())
                .setTotal(res.getTotal())
                .setRecords(res.getRecords());

    }


    @Override
    public PageResult<TFinanceData> getFinanceDataList(int page, int size, String beginTime, String endTime, String curWeek, String curMonth) {
        if (StringUtils.isNotBlank(curWeek) || StringUtils.isNotBlank(curMonth)) {
            beginTime = "";
            endTime = "";
            if (StringUtils.isNotBlank(curMonth)) {
                page = 1;
                size = 31;
            }
            if (StringUtils.isNotBlank(curWeek) && StringUtils.isNotBlank(curMonth)) {
                curWeek = "";
                curMonth = "";
            }
        }
        Page<TFinanceData> res = financeDataMapper.selectFinanceDataList(new Page<>(page, size), beginTime, endTime, curWeek, curMonth);
        return new PageResult<TFinanceData>()
                .setCurrent(res.getCurrent())
                .setPages(res.getPages())
                .setSize(res.getSize())
                .setTotal(res.getTotal())
                .setRecords(res.getRecords());
    }

    @Override
    public Map<String, String> getIndexDashboardData() {
        Map<String, String> res = financeDataMapper.selectIndexData();
        String companyCommission = String.valueOf(res.get("companyCommission"));
        String transferGet = String.valueOf(res.get("transfer_get"));
        BigDecimal total = new BigDecimal(companyCommission).add(new BigDecimal(transferGet));
        res.put("companyCommission", total.toString());
        return res;
    }

    @Override
    public PageResult<BalanceLogDTO> balanceLog(int page, int size, String nickName, String id, String mobile,
                                                String method, String status, String addBeginTime, String addEndTIme,
                                                String name, String tradeType,String mId) {
        Page<Map<String, Object>> res = memberBalanceLogMapper.selectBalanceLog(new Page<>(page, size),
                nickName, id, mobile, method, status, addBeginTime, addEndTIme, name, tradeType,mId);
        List<BalanceLogDTO> result = res.getRecords()
                .stream()
                .map(m -> {
                    Map<String, String> map = Maps.transformEntries(m, (k, v) -> String.valueOf(v));
                    return new BalanceLogDTO()
                            .setTradeNo(map.get("trade_no"))
                            .setNickName(map.get("nick_name"))
                            .setName(map.get("name"))
                            .setMoney((new BigDecimal(map.get("money")).add(new BigDecimal(map.get("fee")))).toString())
                            .setRealMoney(map.get("money"))
                            .setMethod(map.get("method"))
                            .setBalance(map.get("balance"))
                            .setStatus(map.get("status"))
                            .setAddTime(map.get("add_time"))
                            .setEndTime(map.get("end_time"))
                            .setMobile(map.get("mobile"))
                            .setMAutoId(map.get("m_auto"))
                            .setPayType(map.get("recharge_type"))
                            .setMId(map.get("m_id"))
                            .setBefore(map.get("before_m"))
                            .setTips(map.get("tips"));

                }).collect(Collectors.toList());
        return new PageResult<BalanceLogDTO>()
                .setRecords(result)
                .setTotal(res.getTotal())
                .setPages(res.getPages())
                .setSize(res.getSize())
                .setCurrent(res.getCurrent());

    }

    @Override
    public DashboardVo getIndexDashboardData(LocalDate beginTime, LocalDate endTime) {
        Map<String, String> cMap =
                financeDataMapper
                        .selectCompanyCommission(beginTime, endTime)
                        .stream()
                        .map(m -> {
                            String time = m.get("cd");
                            Map<String, String> map = new HashMap<>();
                            TMemberBalanceLog fee = financeDataMapper.selectBalanceFee(DateUtils.localDateOfStr(time));
                            BigDecimal total = new BigDecimal(String.valueOf(m.get("cc"))).add(fee.getFee());
                            map.put(String.valueOf(time), total.toString());
                            return map;
                        })
                        .flatMap(fm -> fm.entrySet().stream())
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(v1,v2)->(new BigDecimal(v1).add(new BigDecimal(v2))).toString()));

        boolean isNow = !(beginTime != null && endTime != null);
        LocalDate now = isNow ? LocalDate.now() : beginTime;
        Integer start = 0;
        Integer end = 1;
        if (isNow)
            end = now.getDayOfMonth();
        else
            end += (int) (endTime.toEpochDay() - beginTime.toEpochDay());

        SortedMap<String, Integer> res =
                IntStream
                        .range(start, end)
                        .mapToObj(
                                i -> {
                                    LocalDate date =
                                            isNow ? LocalDate.of(now.getYear(), now.getMonthValue(), 1) : now;
                                    Map<String, Integer> m = new HashMap<>();
                                    String startTime = DateUtils.getLocalDateStr(date.plusDays(i));
                                    m.put(startTime, 0);
                                    return m;
                                }
                        )
                        .flatMap(fm -> fm.entrySet().stream())
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (k1, k2) -> k2, TreeMap::new));

        res.putAll(
                financeDataMapper
                        .selectMemberCountWithDate(beginTime, endTime)
                        .stream()
                        .map(m -> {
                                    String time = m.get("md");
                                    Map<String, Integer> map = new HashMap<>();
                                    map.put(String.valueOf(time), Integer.parseInt(String.valueOf(m.get("mc"))));
                                    return map;
                                }
                        )
                        .flatMap(fm -> fm.
                                entrySet().
                                stream().
                                filter(f -> f.getKey() != null && f.getValue() != null)
                        )
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1+v2)));
        DashboardVo vo = new DashboardVo();
        res
                .entrySet()
                .stream()
                .forEachOrdered(m ->
                        {
                            vo.getDate().add(m.getKey());
                            vo.getRegistry().add(m.getValue());
                            vo.getCompanyCommission().add(cMap.get(m.getKey()) == null ? "0" : cMap.get(m.getKey()));
                        }
                );


        return vo;
    }

    @Override
    public PageResult<TPreserveData> getPreserveDataList(int page, int size, String beginTime, String endTime, String curWeek, String curMonth) {
        Page<TPreserveData> res = preserveDataMapper.selectPreserveDataList(new Page<>(page, size), beginTime, endTime, curWeek, curMonth);
        return new PageResult<TPreserveData>()
                .setCurrent(res.getCurrent())
                .setPages(res.getPages())
                .setSize(res.getSize())
                .setTotal(res.getTotal())
                .setRecords(res.getRecords());
    }
}
